export default {
    install: function (Vue) {
        //根据项目需求，进一步封装vue的http，主要是减少写提示消息的相关代码
        let defaultHttpConfig = {
            options: {  //发送给后台时携带cookie或者设置headers
                withCredentials: true
            },
            fullSuccess: false, /*是否成功的回调函数全部自己定义，如果为true则直接将response.data(后台返回数据在response.data中)放置到resolve中，fullSuccess设置为true后，ignoreEmptyData、hideEmptyTip、showEmptyInfo、emptyDataInfo这四个字段均可以不设置，设置也不会起作用；
                                如果为false，则提示消息全使用此函数默认提示方式，会将response.data[dataKey]放置到resolve中*/
            ignoreEmptyData: false, //设置为true，则不判断后台返回的前台使用的数据是否为空的情况，直接进行消息提示，为false则进行提示，默认是提示数据为空，如果hideEmptyTip设置为true，则不提示消息
            hideEmptyTip: false, //数据为空时，是否显示数据为空的消息提示，默认显示消息提示
            showEmptyInfo:false,//数据为空时，是否使用后台返回的消息进行消息提示
            emptyDataInfo: null, //数据为空时，可提示自定义的数据为空的提示信息
            successInfo:null,//请求成功的消息提示，默认使用后台返回的消息进行提示，
            hideSuccessTip: false, //是否显示请求成功的提示，默认显示提示信息
            useDesc: false, //是否启用后台返回的desc字段作为提示信息
            hideErrorTip: false, //是否显示请求错误的提示，默认显示提示信息
            redirectUrl:'/login',  //报403或者401错误时，重定向页面的路由
            // redirectUrl:'',  //报403或者401错误时，重定向页面的路由
            redirectInterval:3000,  //报403或者401错误时，重定向页面的路由等候的时间，默认3s
            messageKey: 'message',  //后台放置提示消息的字段
            dataKey: 'value',  //后台放置前台需求数据的字段
        };
        /**
         * @param
         *  type:默认值 get ，请求类型，默认只有四种，大小写均可.
         *  url:默认值 null ，请求后台的url.
         *  param: {},  默认值{} ,请求后台的参数 requestBody；如果参数是requestParameter，则可以追加在url后，也可以放在options里{params:HttpParams}
         *  configOptions: 默认值 defaultHttpConfig
         **/
        Vue.prototype.httpRequest = function(type = 'get',url= null,param = {}, configOptions = {}) {
            const self = this,requestType = type.toLowerCase();
            let defaultOptions = self.cloneObj(defaultHttpConfig); //使用clone保证不更改默认config
          //传递Authorization
          let userInfo =  sessionStorage.getItem('userInfo');
          if(userInfo != null &&  userInfo != undefined && userInfo != '{}'){
            defaultOptions.options.headers = {Authorization:JSON.parse(userInfo).Authorization};
          }
            let config = Object.assign(defaultOptions, configOptions); //默认config和传入的config合并
            //_是lodash，判断url是不是空，为空的话进行提示，不继续执行
            if (self._.isEmpty(url)) {self.message(self, "warn", "必须传入请求后台的url");return; }
            let request = null; //axios返回的promise对象
            if(requestType == 'get' || requestType == 'delete'){
                request = self.axios[requestType](url,config.options);
            }else if(requestType == 'put' || requestType == 'post'){
                request = self.axios[requestType](url,param,config.options);
            }else{
                return;
            }
            //判断请求是不是空，为空的话进行提示，不继续执行
            if (request == null) {self.message(self, "warn", "配置项配置错误，请检查配置项");return;}
            //再使用Promise进行返回，是因为接收到返回数据后会在Promise中进行部分数据判断等
            return new Promise((resolve,reject)=>{
                request.then((response) => {
                    const res = response.data; //后台返回的数据
                    //fullSuccess设置为true，则直接将后台返回的数据抛出；若为false，则再进行后续数据判断
                    if (config.fullSuccess) {
                        resolve(res);
                    } else {
                        const data = res[config.dataKey]; //获取后台返回数据中前台使用的数据，dataKey一般为data或者value
                        if(!self.isEmpty(res.status)){  //后台返回response有status字段，前台需要判断status是否为200
                            if(res['status'] == 200){
                              resolve(data); //不管数据是否为空，都将后台返回的前台使用的数据抛出
                              if (!config.ignoreEmptyData) { //ignoreEmptyData设置为true，则不判断后台返回的前台使用的数据是否为空的情况，直接进行消息提示
                                //判断后台返回的前台使用的数据是否为空，空的情况包含null,undefined,'',[],{}；
                                if (self.isEmpty(data) || (self.isObjOrArr(data) == 'array' && data.length == 0) || (self.isObjOrArr(data) == 'object' && self.isEmptyObject(data))) {
                                  /* hideEmptyTip: 是否隐藏数据为空的消息提示，再保存更新数据时一般设置为true，不进行数据为空的消息提示
                                     showEmptyInfo:是否使用后台返回的消息进行消息提示
                                     emptyDataInfo：自定义数据为空的消息提示
                                  */
                                  !config.hideEmptyTip && (config.showEmptyInfo ? self.message(self, "success",res[config.messageKey]) : self.message(self,"info",config.emptyDataInfo ? config.emptyDataInfo : "数据为空" ))
                                } else { //数据不为空，是否进行消息提示，hideSuccessTip为true时，不进行消息提示,successInfo:自定义的成功提示内容
                                  !config.hideSuccessTip && self.message(self, "success", config.successInfo ?config.successInfo : res[config.messageKey]);
                                }
                              } else {
                                !config.hideSuccessTip && self.message(self, "success", config.successInfo ?config.successInfo : res[config.messageKey]); //是否进行消息提示
                              }
                            }else{ //其他状态码的回调
                              reject(res);//将错误信息抛出
                                //是否进行错误消息提示，默认进行提示
                                if(!config.hideErrorTip){
                                    let info = null;
                                  if (config.useDesc) { //判断是否使用后台返回数据的desc字段值进行消息提示，默认使用messageKey字段中的值作为消息提示
                                    info = self.isEmpty(res["desc"]) ? res[config.messageKey] :res["desc"];
                                  } else {
                                    info = res[config.messageKey];
                                  }
                                  if (res.status == 403 || res.status == 401) { //权限不足，3s后默认重定向到登录页，可自定义配置
                                    console.log(self.$route,self.$router);
                                    if(-1 == self.$route.path.indexOf('login')){
                                      self.message(self, 'warn', `${info}<br>${config.redirectInterval/1000}s后跳转至登录页`, true);
                                      let timer = setTimeout(() => { self.$router.push({path: config.redirectUrl});clearTimeout(timer);timer = null;}, config.redirectinterval);
                                    }else{
                                      self.message(self, 'warn', info);
                                    }
                                  }else{
                                    self.message(self,'error', info);
                                  }
                                }
                            }
                        }else{ //后台返回response无status字段，进入此处则表示是成功回调（需要后台配合保证无status时，返回的是成功回调）
                          resolve(data);
                          if (!config.ignoreEmptyData) {//ignoreEmptyData设置为true，则不判断后台返回的前台使用的数据是否为空的情况，直接进行消息提示
                            if (self.isEmpty(data) || (self.isObjOrArr(data) == 'array' && data.length == 0) || (self.isObjOrArr(data) == 'object' && self.isEmptyObject(data))) {
                              !config.hideEmptyTip && (config.showEmptyInfo ? self.message(self, "success",res[config.messageKey]) : self.message(self,"info",config.emptyDataInfo ? config.emptyDataInfo : "数据为空" ))
                            } else {
                              !config.hideSuccessTip && self.message(self, "success", config.successInfo ?config.successInfo : res[config.messageKey]);
                            }
                          } else {
                            !config.hideSuccessTip && self.message(self, "success", config.successInfo ?config.successInfo :res[config.messageKey]);
                          }
                        }
                    }
                }).catch(function (error) {
                    //hideErrorTip：是否隐藏请求返回错误的消息提示
                    if (config.hideErrorTip){
                        reject(error);return;
                    }else{
                        const err = error.response;
                        //判断错误消息的response是否存在，不存在则直接进行错误返回提示，404等错误会没有response,Network Error 也没有response
                        if(!err){
                            self.message(self, 'error',error);
                            reject(error);
                            return ;
                        }
                        const res = err.data;
                        reject(res);
                        //判断错误消息的response.data是否存在，不存在则直接进行错误返回提示statusText字段信息
                        if (self._.isEmpty(res)) {
                            self.message(self, 'error', err.statusText);
                            return;
                        }
                      let info = null;
                      if (config.useDesc) {
                        info = self.isEmpty(res["desc"]) ?res[config.messageKey] :res["desc"];
                      } else {
                        info = res[config.messageKey];
                      }
                        //判断后台返回的状态码是否是401或者403
                        if (err.status == 403 || err.status == 401) { //权限不足
                          console.log('error',self.$route,self.$router);
                          if(-1 == self.$route.path.indexOf('login')){
                            self.message(self, 'warn', `${info}<br>${config.redirectInterval/1000}s后跳转至登录页`, true);
                            let timer = setTimeout(() => { self.$router.push({path: config.redirectUrl});clearTimeout(timer);timer = null;}, config.redirectinterval);
                          }else{
                            self.message(self, 'warn', info);
                          }
                        } else {
                            self.message(self, 'error', info);
                        }
                    }
                })
            })
        };
    }
}
